/*!
 * \file WTSCfgLoader.cpp
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief WTS配置文件加载器实现文件
 * 
 * \details 本文件实现了WTS配置文件加载器的具体功能，支持JSON和YAML格式的配置文件解析。
 *          主要功能包括：
 *          - JSON格式配置文件解析（基于RapidJSON）
 *          - YAML格式配置文件解析（基于yaml-cpp）
 *          - 递归解析嵌套的配置结构
 *          - 跨平台的字符编码处理
 *          - 统一的WTSVariant数据结构转换
 */
#include "WTSCfgLoader.h"
#include "../Share/StrUtil.hpp"
#include "../Share/StdUtils.hpp"

#ifdef _WIN32
#include "../Share/charconv.hpp"
#endif

#include "../Includes/WTSVariant.hpp"
#include <rapidjson/document.h>
namespace rj = rapidjson;

/*!
 * \brief 将JSON值转换为WTSVariant对象
 * 
 * \details 递归地将RapidJSON的Value对象转换为WTSVariant对象，支持：
 *          - 对象类型（Object）：转换为WTSVariant对象
 *          - 数组类型（Array）：转换为WTSVariant数组
 *          - 数值类型（Number）：支持int、uint、int64、uint64、double
 *          - 字符串类型（String）：转换为字符串
 *          - 布尔类型（Boolean）：转换为布尔值
 *          
 *          该函数采用递归方式处理嵌套的JSON结构，确保完整的数据转换。
 * 
 * \param root RapidJSON的Value对象引用
 * \param params 目标WTSVariant对象指针
 * \return bool 转换是否成功
 * 
 * \note 要求root和params的类型匹配（对象对对象，数组对数组）
 */
bool json_to_variant(const rj::Value& root, WTSVariant* params)
{
	// 类型匹配检查
	if (root.IsObject() && params->type() != WTSVariant::VT_Object)
		return false;

	if (root.IsArray() && params->type() != WTSVariant::VT_Array)
		return false;

	if (root.IsObject())
	{
		// 处理JSON对象
		for (auto& m : root.GetObject())
		{
			const char* key = m.name.GetString();
			const rj::Value& item = m.value;
			switch (item.GetType())
			{
			case rj::kObjectType:
			{
				// 递归处理嵌套对象
				WTSVariant* subObj = WTSVariant::createObject();
				if (json_to_variant(item, subObj))
					params->append(key, subObj, false);
			}
			break;
			case rj::kArrayType:
			{
				// 递归处理嵌套数组
				WTSVariant* subAy = WTSVariant::createArray();
				if (json_to_variant(item, subAy))
					params->append(key, subAy, false);
			}
			break;
			case rj::kNumberType:
				// 处理各种数值类型
				if (item.IsInt())
					params->append(key, item.GetInt());
				else if (item.IsUint())
					params->append(key, item.GetUint());
				else if (item.IsInt64())
					params->append(key, item.GetInt64());
				else if (item.IsUint64())
					params->append(key, item.GetUint64());
				else if (item.IsDouble())
					params->append(key, item.GetDouble());
				break;
			case rj::kStringType:
				// 处理字符串类型
				params->append(key, item.GetString());
				break;
			case rj::kTrueType:
			case rj::kFalseType:
				// 处理布尔类型
				params->append(key, item.GetBool());
				break;

			}
		}
	}
	else
	{
		// 处理JSON数组
		for (auto& item : root.GetArray())
		{
			switch (item.GetType())
			{
			case rj::kObjectType:
			{
				// 递归处理数组中的对象
				WTSVariant* subObj = WTSVariant::createObject();
				if (json_to_variant(item, subObj))
					params->append(subObj, false);
			}
			break;
			case rj::kArrayType:
			{
				// 递归处理数组中的数组
				WTSVariant* subAy = WTSVariant::createArray();
				if (json_to_variant(item, subAy))
					params->append(subAy, false);
			}
			break;
			case rj::kNumberType:
				// 处理数组中的数值
				if (item.IsInt())
					params->append(item.GetInt());
				else if (item.IsUint())
					params->append(item.GetUint());
				else if (item.IsInt64())
					params->append(item.GetInt64());
				else if (item.IsUint64())
					params->append(item.GetUint64());
				else if (item.IsDouble())
					params->append(item.GetDouble());
				break;
			case rj::kStringType:
				// 处理数组中的字符串
				params->append(item.GetString());
				break;
			case rj::kTrueType:
			case rj::kFalseType:
				// 处理数组中的布尔值
				params->append(item.GetBool());
				break;
			}
		}
	}
	return true;
}

WTSVariant* WTSCfgLoader::load_from_json(const char* content)
{
	// 解析JSON文档
	rj::Document root;
	root.Parse(content);

	// 检查解析错误
	if (root.HasParseError())
		return NULL;

	// 创建返回对象并转换
	WTSVariant* ret = WTSVariant::createObject();
	if (!json_to_variant(root, ret))
	{
		ret->release();
		return NULL;
	}

	return ret;
}

#include "../WTSUtils/yamlcpp/yaml.h"

/*!
 * \brief 将YAML节点转换为WTSVariant对象
 * 
 * \details 递归地将yaml-cpp的Node对象转换为WTSVariant对象，支持：
 *          - 映射类型（Map）：转换为WTSVariant对象
 *          - 序列类型（Sequence）：转换为WTSVariant数组
 *          - 标量类型（Scalar）：转换为字符串
 *          
 *          该函数采用递归方式处理嵌套的YAML结构，确保完整的数据转换。
 * 
 * \param root yaml-cpp的Node对象引用
 * \param params 目标WTSVariant对象指针
 * \return bool 转换是否成功
 * 
 * \note YAML的所有标量值都转换为字符串类型
 */
bool yaml_to_variant(const YAML::Node& root, WTSVariant* params)
{
	// 类型匹配检查
	if (root.IsNull() && params->type() != WTSVariant::VT_Object)
		return false;

	if (root.IsSequence() && params->type() != WTSVariant::VT_Array)
		return false;

	bool isMap = root.IsMap();
	for (auto& m : root)
	{
		// 获取键值（仅对映射类型有效）
		std::string key = isMap ? m.first.as<std::string>() : "";
		const YAML::Node& item = isMap ? m.second : m;
		switch (item.Type())
		{
		case YAML::NodeType::Map:
		{
			// 递归处理嵌套映射
			WTSVariant* subObj = WTSVariant::createObject();
			if (yaml_to_variant(item, subObj))
			{
				if(isMap)
					params->append(key.c_str(), subObj, false);
				else
					params->append(subObj, false);
			}
		}
		break;
		case YAML::NodeType::Sequence:
		{
			// 递归处理嵌套序列
			WTSVariant* subAy = WTSVariant::createArray();
			if (yaml_to_variant(item, subAy))
			{
				if (isMap)
					params->append(key.c_str(), subAy, false);
				else
					params->append(subAy, false);
			}
		}
		break;
		case YAML::NodeType::Scalar:
			// 处理标量值（转换为字符串）
			if (isMap)
				params->append(key.c_str(), item.as<std::string>().c_str());
			else
				params->append(item.as<std::string>().c_str());
			break;
		}
	}

	return true;
}

WTSVariant* WTSCfgLoader::load_from_yaml(const char* content)
{
	// 加载YAML文档
	YAML::Node root = YAML::Load(content);

	// 检查是否为空
	if (root.IsNull())
		return NULL;

	// 创建返回对象并转换
	WTSVariant* ret = WTSVariant::createObject();
	if (!yaml_to_variant(root, ret))
	{
		ret->release();
		return NULL;
	}

	return ret;
}

WTSVariant* WTSCfgLoader::load_from_content(const std::string& content, bool isYaml /* = false */, bool isUTF8 /* = true */)
{
	std::string buffer;
#ifdef _WIN32
	// Windows平台UTF-8编码转换
	if (isUTF8)
		buffer = UTF8toChar(content);
#endif

	if (buffer.empty())
		buffer = content;

	// 根据格式类型选择解析器
	if (isYaml)
		return load_from_yaml(buffer.c_str());
	else
		return load_from_json(buffer.c_str());
}

WTSVariant* WTSCfgLoader::load_from_file(const char* filename, bool isUTF8 /* = true */)
{
	// 检查文件是否存在
	if (!StdFile::exists(filename))
		return NULL;

	// 读取文件内容
	std::string content;
	StdFile::read_file_content(filename, content);
	if (content.empty())
		return NULL;

	// 字符编码处理
	// Linux下默认UTF8编码
	// Windows下默认GBK编码
#ifdef _WIN32
	if(isUTF8)
		content = UTF8toChar(content);
#endif

	// 根据文件扩展名选择解析器
	if (StrUtil::endsWith(filename, ".json"))
		return load_from_json(content.c_str());
	else if (StrUtil::endsWith(filename, ".yaml") || StrUtil::endsWith(filename, ".yml"))
		return load_from_yaml(content.c_str());

	return NULL;
}
